package com.web.webstart.base.controller;

import com.web.webstart.base.constant.XaConstant;
import com.web.webstart.base.exception.BaseException;
import com.web.webstart.base.exception.BusinessException;
import com.web.webstart.base.exception.DatabaseException;
import com.web.webstart.base.exception.ValidationException;
import com.web.webstart.base.util.result.XaResult;
import org.apache.log4j.Logger;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.persistence.PersistenceException;
import java.net.SocketException;

/**
 * 基础控制器类
 * @author zj
 *
 * @ExceptionHandler 来进行异常处理 @link {http://blog.csdn.net/u013632755/article/details/49908621}
 *
 * java.net.SocketException: Connection reset by peer: socket write error
 * java.net.SocketException: Software caused connection abort: socket write error
 * javax.persistence.PersistenceException: unexpected error when rollbacking
 * javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException   数据库连接池的问题，已经断开的链接，数据库连接池继续提供给应用使用
 */
public abstract class BaseController {

    private static final Logger LOGGER = Logger.getLogger(BaseController.class);

    @ExceptionHandler(Exception.class)
    public @ResponseBody
    XaResult<T> handleUncaughtException(Exception ex) {			//系统异常
        LOGGER.error("系统异常(0)："+ex.getMessage(), ex);
        return new XaResult<T>(ex instanceof BaseException ? ex.getMessage() : XaConstant.Message.error,  XaConstant.Code.error);
    }

    @ExceptionHandler(ValidationException.class)
    public @ResponseBody
    XaResult<T> handleValidationException(ValidationException validationEx) {		//数据校验异常
        LOGGER.error("验证异常(1)："+validationEx.getMessage(), validationEx);
        return new XaResult<T>(validationEx.getMessage(), XaConstant.Code.code_database_failure);
    }

    @ExceptionHandler(BusinessException.class)
    public @ResponseBody
    XaResult<T> handleBusinessException(BusinessException businessEx) {	//业务逻辑异常
        LOGGER.error("业务异常(2)："+businessEx.getMessage(), businessEx);
        return new XaResult<T>(businessEx.getMessage(),
                XaConstant.Message.object_not_find.equals(businessEx.getMessage()) ?
                        XaConstant.Code.code_objectNotFand_failure :
                        XaConstant.Code.code_business_failure);
    }

    @ExceptionHandler(DatabaseException.class)
    public @ResponseBody
    XaResult<T> handleValidationException(DatabaseException dbEx) {		//数据库操作异常
        LOGGER.error("数据库操作异常(3)："+dbEx.getMessage(), dbEx);
        return new XaResult<T>(dbEx.getMessage(), XaConstant.Code.code_database_failure);
    }


    @ExceptionHandler(HttpMessageConversionException.class)
    public @ResponseBody
    XaResult<T> handleJSONConvertException(HttpMessageConversionException jsonEx) {    //JSON格式转换异常
        LOGGER.error("json异常(4)：" + jsonEx.getMessage(), jsonEx);
        return new XaResult<T>("JSON格式转换异常",
                (jsonEx instanceof HttpMessageNotReadableException)
                        ? XaConstant.Code.code_json_failure_reade :
                        XaConstant.Code.code_json_failure_wirte);
    }

    @ExceptionHandler(ServletRequestBindingException.class)
    public @ResponseBody
    XaResult<T> handleRequestException(ServletRequestBindingException ex) {		//请求参数异常
        LOGGER.error("请求参数异常(5)："+ex.getMessage(), ex);
        String errorMsg = ex.getLocalizedMessage();
        if (ex instanceof MissingServletRequestParameterException) {
            errorMsg = "paramter参数缺失异常,请检查参数名称大小写，有无空格等：" + errorMsg;
        } else  if (ex instanceof MissingPathVariableException) {
            errorMsg = "path参数缺失异常：" + errorMsg;
        }
        return new XaResult<T>(errorMsg, XaConstant.Code.code_request_parameter_failure);
    }

    @ExceptionHandler(SocketException.class) //http://developer.51cto.com/art/201003/189724.htm
    public
    @ResponseBody
    XaResult<T> handleSocketExceptionException(SocketException ex) {            //Socket异常
        LOGGER.error("Socket异常(6)：" + ex.getMessage(), ex);
        int socketErroType = 10;
        if (ex.getLocalizedMessage().contains("java.net.SocketException: Connection reset by peer: socket write error")) {
            socketErroType = 11;
        } else  if (ex.getLocalizedMessage().contains("java.net.SocketException: Software caused connection abort: socket write error")) {
            socketErroType = 12;
        }
        return new XaResult<T>(socketErroType + "|" + ex.getLocalizedMessage(), XaConstant.Code.code_socket_failure);
    }

    @ExceptionHandler(PersistenceException.class)
    public
    @ResponseBody
    XaResult<T> handlePersistenceException(PersistenceException ex) {            //数据持久化异常
        LOGGER.error("数据持久化异常(7)：" + ex.getMessage(), ex);
        int persisitenceErroType = 20;
        if (ex.getLocalizedMessage().contains("javax.persistence.PersistenceException: unexpected error when rollbacking")) {
            persisitenceErroType = 21;
        } else  if (ex.getLocalizedMessage().equals("javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException")) {
            persisitenceErroType = 22;
        }
        return new XaResult<T>(persisitenceErroType + "|" + ex.getLocalizedMessage(), XaConstant.Code.code_database_failure);
    }

    @ExceptionHandler(TypeMismatchException.class)
    public
    @ResponseBody
    XaResult<T> handleTypeMismatchException(TypeMismatchException ex) {            //方法参数异常
        LOGGER.error("方法参数异常(8)，请检查类型,后台 defaultValue 取值有问题" + ex.getMessage(), ex);
        return new XaResult<T>( ex.getLocalizedMessage() , XaConstant.Code.code_request_type_mismatch_failure);
    }

    @ExceptionHandler(HttpMediaTypeException.class)
    public
    @ResponseBody
    XaResult<T> handleHttpMediaTypeException(HttpMediaTypeException ex) {            //方法参数异常
        LOGGER.error("HttpMediaType异常(8)，请检查" + ex.getMessage(), ex);
        return new XaResult<T>( "HttpMediaType错误，请检查" , XaConstant.Code.error);
    }
}
